package com.itheima.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/*用注解的方式来进行*/
//通知类，告诉spring在增强的前后需要做什么事
@Component
@Aspect //代替了<aop:aspect ref="advice">，该类即是一个通知类也是一个切面类
public class Advice {

    //定义切入点表达式
    @Pointcut("execution(* com.itheima.service.StudentService.*(..))")
    //@Pointcut("execution(* com.itheima.service.StudentService.insert(..))")
    public void pt(){}

   /* @Pointcut("execution(* com.itheima.service.StudentService.update(..))")
    public void pt2(){}*/

    /*
    也可以将上面2个进行结合(这里主要想表达的是; 可以使用逻辑判断)
    @Pointcut("execution(* com.itheima.service.StudentService.update(..)) || execution(* com.itheima.service.StudentService.insert(..))")
    public void pt3(){}*/

    @Before("pt()")
   // @Before("pt()||pt2()") //还可以自己选择对那些方法进行增强
    public void before(){
        //前置通知：开启事务
        System.out.println("前置通知：开启事务");
    }

    @AfterReturning("pt()")
    public void afterReturn(){
        //后置通知：提交事务
        System.out.println("后置通知：提交事务");
    }

    @AfterThrowing("pt()")
    public void afterThrowable(){
        //异常通知：回滚事务
        System.out.println("异常通知：回滚事务");
    }

    @After("pt()")
    public void after(){
        //最终通知：释放资源
        System.out.println("最终通知：释放资源");
    }

    //==========================================
    //环绕通知
    @Around("pt()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        Object proceed = null;
        try {
            before();//调用前置通知方法
            Object[] args = proceedingJoinPoint.getArgs(); //获得目标方法的参数
            proceed = proceedingJoinPoint.proceed(args);//执行目标方法的原方法
            afterReturn();//调用后置通知方法
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            afterThrowable();//调用异常通知方法
        } finally {
            after();//调用终结方法
        }
        return proceed; //返回方法执行的结果
    }
}
